package galaxy_provide

import (
	"context"
	"os"
	"time"

	"gddgame.cc/galaxy"
	"gddgame.cc/galaxy/asteroid"
	"gddgame.cc/galaxy/asteroid/adapt/redis"
	"gddgame.cc/galaxy/binocle"
	"gddgame.cc/galaxy/common/bootstrap"
	"gddgame.cc/galaxy/server/composer"
	"gddgame.cc/galaxy/utils/def"
)

type coreTarget struct {
	Core binocle.Core `galaxy:"inject"`

	composer.Composer `inject:""`

	Logger def.Logger      `inject:""`
	Config *galaxy.Config  `inject:""`
	Boot   *bootstrap.Boot `inject:""`
}

func CoreProvide() galaxy.ServerProvider {
	t := &coreTarget{}
	return galaxy.ServerProvider{
		Name:   "binocle_core",
		Inject: t,
		OnCreate: func() error {
			namespace := ""
			dataCenter := ""
			dataCenterConfig := galaxy.Config{}
			if v := t.Config.Read("namespace"); v != nil {
				namespace = v.(string)
			} else {
				namespace = binocle.DefaultNamespace
			}
			group := ""
			if v := t.Config.Read("group"); v != nil {
				group = v.(string)
			} else {
				group = binocle.DefaultGroup
			}
			if v := t.Config.Read("data_center"); v != nil {
				dataCenter = v.(string)
				// 读取data_center
				if err := dataCenterConfig.LoadName("dc"); err != nil {
					return err
				}
			} else if dataCenter = os.Getenv("DATA_CENTER"); dataCenter != "" {
				// 读取data_center
				if err := dataCenterConfig.LoadName("dc"); err != nil {
					return err
				}
			} else {
				dataCenter = binocle.DefaultDataCenter
			}
			core := binocle.NewCore(t.Logger, namespace, group, dataCenter, dataCenterConfig.All(), func(prefix string) asteroid.Adapt {
				if adapt, ok := adapts.Load(prefix); ok {
					return adapt.(asteroid.Adapt)
				} else {
					adapt := redis.NewAdapt(t.Boot.Redis(), time.Second*15, prefix)
					adapts.Store(prefix, adapt)
					return adapt
				}
			})

			t.Core = core
			return nil
		},
		OnStart: func(ctx context.Context) error {
			if err := t.Core.Start(); err != nil {
				return err
			}
			t.Core.Cluster().AttachContext(ctx)
			return nil
		},
		OnStop: func() error {
			if err := t.Core.Close(); err != nil {
				return err
			}
			return nil
		},
	}
}
